package ncu.me.musicplayer.http;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ncu.me.musicplayer.MyApplication;
import ncu.me.musicplayer.entity.MusicInfo;
import ncu.me.musicplayer.model.SearchModel;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * @Author ye
 * @Date 2020/6/1 21:56
 * @Version 1.0
 */
public class MusicHttp implements IMusicHttp {
    OkHttpClient mOkHttpClient;
    String baseUrl = "https://api.qq.jsososo.com/";
    public MusicHttp(){
        mOkHttpClient = new OkHttpClient.Builder().build();

    }

    List<MusicInfo> getMusicInfo(String key){
        File file = new File(MyApplication.sAppContext.getCacheDir() + "/temp/"+key);
        if (file.exists()){
            try {
                FileInputStream inputStream = new FileInputStream(file);
                byte[] buf = new byte[inputStream.available()];
                inputStream.read(buf);
                inputStream.close();
                String text = new String(buf);
                Gson gson = new Gson();
                SearchModel model = gson.fromJson(text, SearchModel.class);
                if (model.getResult()==100){
                    List<MusicInfo> musicInfos = new ArrayList<>();
                    model.getData().getList().forEach(listBean -> {
                        MusicInfo musicInfo = new MusicInfo();
                        musicInfo.setSongName(listBean.getSongname());
                        musicInfo.setName(listBean.getSinger().get(0).getName());
                        musicInfo.setMid(listBean.getSongmid());
                        musicInfos.add(musicInfo);
                    });
                    return musicInfos;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    void save(String text,String key){
        File dir = new File(MyApplication.sAppContext.getCacheDir() + "/temp");
        if (!dir.exists()){
            dir.mkdir();
        }
        File file = new File(dir + "/"+key);
        try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
            fileOutputStream.write(text.getBytes());
            fileOutputStream.flush();
        }catch (Exception e){}
    }
    @Override
    public void search(String key, SearchResult result) {

        List<MusicInfo> infos = getMusicInfo(key);
        if (infos != null && infos.size() > 0){
            result.onSuccess(infos);
            return;
        }

        Request request = new Request.Builder()
                .url(baseUrl+"search?key="+key)
                .headers(getHeaders())
                .build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                result.onError(e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if (response.isSuccessful()){
                    String content = response.body().string();
                    save(content,key);
                    try{
                        List<MusicInfo> musicInfos = new ArrayList<>();
                        Gson gson = new Gson();
                        SearchModel model = gson.fromJson(content, SearchModel.class);
                        if (model.getResult()==100){
                            model.getData().getList().forEach(listBean -> {
                                MusicInfo musicInfo = new MusicInfo();
                                musicInfo.setSongName(listBean.getSongname());
                                musicInfo.setName(listBean.getSinger().get(0).getName());
                                musicInfo.setMid(listBean.getSongmid());
                                musicInfos.add(musicInfo);
                            });
                            result.onSuccess(musicInfos);

                        }else{
                            result.onFailure(content);
                        }
                    }catch (Exception e){
                        result.onError(e);
                        result.onFailure(content);
                    }


                }else {
                    result.onFailure(response.body().string());
                }
            }
        });
    }

    @Override
    public void get(String mid, GetResult result) {

    }

    @Override
    public void download(String mid, DownloadResult result) {
        File dir = new File(MyApplication.sAppContext.getFilesDir()+File.separator+"music");
        if (!dir.exists()){
            dir.mkdir();
        }

        File file = new File(dir+File.separator+mid);
        if (file.exists()){
            result.onSuccess(file.getPath());
            return;
        }
        load(mid, inputStream -> {
            OutputStream outputStream = null;
            try {
                outputStream = new FileOutputStream(file);
                byte[] buffer = new byte[1024];
                int len = -1;
                while ( (len = inputStream.read(buffer) )> 0){
                    outputStream.write(buffer,0,len);
                }
                outputStream.flush();
            } catch (Exception e) {
                result.onError(e);
                return;
            }finally {
                try {
                    outputStream.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            result.onSuccess(file.getPath());
        });

    }
    public void download(String url, StreamResult result) {
        Request request = new Request.Builder()
                .url(url)
                .headers(getHeaders())
                .build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                result.onError(e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if (response.isSuccessful()){
                    try{
                        result.onSuccess(response.body().byteStream());
                    }catch (Exception e){
                        result.onError(e);
                    }

                }else {
                    result.onFailure(response.message());
                }
            }
        });
    }
    @Override
    public void load(String mid, StreamResult result) {
        Request request = new Request.Builder()
                .url(baseUrl+"song/url?id="+mid)
                .headers(getHeaders())
                .build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                result.onError(e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if (response.isSuccessful()){
                    try{
                        Gson gson = new Gson();
                        Map<String,Object> map = gson.fromJson(
                                response.body().string(),
                                new TypeToken<HashMap<String,Object>>(){}.getType());
                        String url = map.get("data").toString();
                        download(url,result);
                    }catch (Exception e){
                        result.onError(e);
                    }

                }else {
                    result.onFailure(response.message());
                }
            }
        });
    }


    Headers getHeaders(){
        return new Headers.Builder()
                .add("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
                .add("Accept-Encoding","gzip, deflate, br")
                .add("Accept-Language","zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
                .add("Cache-Control","gzip, max-age=0")
                .add("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0")
                .build();
    }
}
